'use client';

import type {
  ICreateParentReplyBody,
  IPostClientDetails,
  IPostComment,
  IPostCommentParentReply,
  IPostCommentReply,
  IQueryParams,
} from '@/interfaces';
import type { TBody, TMetadata } from '@/types';
import useUser from '@/hooks/useUser';
import { type ChangeEvent, useEffect, useState } from 'react';
import { useInfiniteQuery, useMutation } from '@tanstack/react-query';
import useToast, { LoginReminderContent } from '@/hooks/useToast';
import {
  createParentReply,
  queryAllParentReplyByReplyId,
} from '@/services/api';
import sanitizeHtml from 'sanitize-html';
import Image from 'next/image';
import { getUserAvatar, toRelativeTime } from '@/lib/tool';
import Link from 'next/link';
import classNames from 'classnames';
import ParentReply from '@/app/[locale]/posts/[id]/ParentReply';
import { useTranslations } from 'use-intl';

export default function Reply({
  replyItem,
  replyIndex,
  commentItem,
  commentIndex,
  postData,
  metadata,
}: {
  replyItem: IPostCommentReply;
  replyIndex: number;
  commentItem: IPostComment;
  commentIndex: number;
  postData: IPostClientDetails;
  metadata: TMetadata;
}) {
  const env = metadata.env;
  const userQuery = useUser(metadata);
  const [replyContent, setReplyContent] = useState('');
  const { show } = useToast();
  const [queryParams, setQueryParams] = useState<IQueryParams>({});
  const [pages, setPages] = useState<IPostCommentParentReply[]>(
    replyItem.content,
  );
  const [isClickLoadMore, setIsClickLoadMore] = useState(false);
  const t = useTranslations('PostIdPage');

  const replyQuery = useInfiniteQuery(
    ['/forum', '/replies', replyItem.reply.id, '/parent', queryParams],
    async (context) => {
      return (await queryAllParentReplyByReplyId({
        id: context.queryKey[2],
        query: {
          ...(context.queryKey[4] as IQueryParams),
          ...context.pageParam,
        },
      })) as IPostCommentReply;
    },
    {
      enabled: isClickLoadMore,
      keepPreviousData: true,
      getPreviousPageParam: (firstPage) => {
        if (firstPage.pageable.previous) {
          return {
            page: Math.max(firstPage.pageable.page - 1, 0),
            size: firstPage.pageable.size,
          };
        }
      },
      getNextPageParam: (lastPage) => {
        if (lastPage.pageable.next) {
          return {
            page: Math.min(lastPage.pageable.page + 1, lastPage.pageable.pages),
            size: lastPage.pageable.size,
          };
        }
      },
      initialData: () => {
        return {
          pages: [replyItem],
          pageParams: [
            {
              page: Math.max(replyItem.pageable.page - 1, 0),
              size: replyItem.pageable.size,
            },
          ],
        };
      },
    },
  );

  useEffect(() => {
    if (replyQuery.data) {
      setPages(
        replyQuery.data.pages
          .flatMap((item) => item.content)
          .map((item) => {
            item.reply._createdOnText = toRelativeTime(item.reply.createdOn);
            return item;
          }),
      );
    }
  }, [replyQuery.data]);

  const createParentReplyMutation = useMutation(
    async (variables: TBody<ICreateParentReplyBody>) => {
      await createParentReply(variables);
      await replyQuery.refetch({ throwOnError: true });
    },
  );

  async function onClickPostReply() {
    if (!userQuery.data?.user) {
      show({
        title: t('notLoggedInPrompt'),
        content: <LoginReminderContent />,
      });
      return;
    }

    const _replyContent = replyContent.trim();
    if (!_replyContent) {
      show({
        type: 'DANGER',
        message: t('replyContentEmptyError'),
      });
      return;
    }

    const content = sanitizeHtml(_replyContent);
    if (!content) {
      show({
        type: 'DANGER',
        message: t('replyContentEmptyError'),
      });
      return;
    }

    try {
      const replyId = replyItem.reply.id;
      await createParentReplyMutation.mutateAsync({
        data: {
          replyId,
          content,
        },
      });

      setReplyContent('');
      show({
        type: 'SUCCESS',
        message: t('replyCompleted'),
      });
    } catch (e) {
      createParentReplyMutation.reset();
      show({
        type: 'DANGER',
        message: e,
      });
    }
  }

  async function onClickLoadMore() {
    setIsClickLoadMore(true);

    try {
      await replyQuery.fetchNextPage();
    } catch (e) {
      show({
        type: 'DANGER',
        message: e,
      });
    }
  }

  function onChangeReplyContent(e: ChangeEvent<HTMLTextAreaElement>) {
    setReplyContent(e.target.value);
  }

  return (
    <div className="vstack gap-4">
      <div className="hstack gap-4">
        <div style={{ width: 64, height: 64 }}>
          <Image
            className="rounded-circle"
            src={getUserAvatar(replyItem.user, metadata).smallAvatarUrl}
            alt={replyItem.user.alias}
            title={replyItem.user.alias}
            width={64}
            height={64}
            placeholder="blur"
            blurDataURL={env.APP_BLUR_DATA_URL}
            style={{
              maxWidth: '100%',
              objectFit: 'cover',
            }}
          />
        </div>

        <div className="vstack">
          <div className="mb-4">
            <div
              dangerouslySetInnerHTML={{
                __html: replyItem.reply.content ?? '',
              }}
            ></div>
          </div>

          <div>
            {userQuery.data?.user && (
              <>
                <a
                  className="user-select-none text-muted text-decoration-none text-decoration-underline-hover"
                  data-bs-toggle="collapse"
                  href={`#yw-r-${replyItem.reply.id}`}
                  role="button"
                  aria-expanded="false"
                  aria-controls={`yw-r-${replyItem.reply.id}`}
                >
                  {t('reply')}
                </a>
                &nbsp;·&nbsp;
              </>
            )}
            <Link
              href={`/users/${replyItem.user.id}`}
              className="text-muted text-decoration-none text-decoration-underline-hover"
            >
              {replyItem.user.alias}
            </Link>
            &nbsp;·&nbsp;
            <span>
              <time
                className={classNames(
                  replyItem.reply._createdOnText ? false : 'invisible',
                )}
                dateTime={replyItem.reply.createdOn}
              >
                {replyItem.reply._createdOnText}
              </time>
            </span>
          </div>

          {userQuery.data?.user && (
            <div className="collapse" id={`yw-r-${replyItem.reply.id}`}>
              <div>
                <textarea
                  className="form-control my-3"
                  rows={4}
                  placeholder={t('enterReply')}
                  name="replyContent"
                  value={replyContent}
                  onChange={onChangeReplyContent}
                ></textarea>
                <button
                  disabled={
                    createParentReplyMutation.isLoading || !replyContent
                  }
                  onClick={onClickPostReply}
                  type="button"
                  className="btn btn-outline-primary my-3 w-100"
                >
                  {createParentReplyMutation.isLoading ? (
                    <span
                      className="spinner-border spinner-border-sm me-2"
                      role="status"
                      aria-hidden="true"
                    ></span>
                  ) : (
                    <i className="bi bi-cursor me-2"></i>
                  )}
                  {t('postReply')}
                </button>
              </div>
            </div>
          )}
        </div>
      </div>

      {pages.length > 0 && (
        <div className="vstack gap-4 mx-5">
          {pages.map((item, index) => {
            return (
              <ParentReply
                key={item.reply.id}
                parentReplyItem={item}
                parentReplyIndex={index}
                replyItem={replyItem}
                replyIndex={replyIndex}
                commentItem={commentItem}
                commentIndex={commentIndex}
                postData={postData}
                metadata={metadata}
              />
            );
          })}
        </div>
      )}

      {replyQuery.hasNextPage && (
        <div className="row mx-6">
          <div className="col rounded">
            <button
              onClick={onClickLoadMore}
              disabled={
                !replyQuery.hasNextPage || replyQuery.isFetchingNextPage
              }
              type="button"
              className="btn btn-light w-100 text-secondary"
            >
              {replyQuery.isFetchingNextPage ? (
                <>
                  <span
                    className="spinner-border spinner-border-sm me-2"
                    role="status"
                    aria-hidden="true"
                  ></span>
                  Loading...
                </>
              ) : (
                <i className="bi bi-three-dots me-2"></i>
              )}
            </button>
          </div>
        </div>
      )}
    </div>
  );
}
